////////////////////////////////////////////////////////////////////////////////
// This file is part of the Mist compiler.                                    //
//                                                                            //
// Copyright (C) 2009 The Mist project                                        //
//                                                                            //
// For a list of contributors, see the COMMITTERS file.                       //
//                                                                            //
// The Mist compiler is free software: you can redistribute it and/or modify  //
// it under the terms of the GNU General Public License as published by       //
// the Free Software Foundation, either version 3 of the License, or          //
// (at your option) any later version.                                        //
//                                                                            //
// The Mist compiler is distributed in the hope that it will be useful,       //
// but WITHOUT ANY WARRANTY; without even the implied warranty of             //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              //
// GNU General Public License for more details.                               //
//                                                                            //
// You should have received a copy of the GNU General Public License          //
// in the COPYING file. If not, see <http://www.gnu.org/licenses/>.           //
////////////////////////////////////////////////////////////////////////////////

///
/// \file
/// Contains the implementation of the TypeSpec methods and related functions.
///

#include "typespec.hpp"

////////////////////////////////////////////////////////////////////////////////
// Includes                                                                   //
////////////////////////////////////////////////////////////////////////////////

#include "common/numeric.hpp"
#include "tree.hpp"

////////////////////////////////////////////////////////////////////////////////
// Function Implementations                                                   //
////////////////////////////////////////////////////////////////////////////////

// bool TypeSpec::incompatible_with_reference(wptr<Reference> ref) const {
// 	// TODO: Fix this
// 	
// 	if (ref->formalTypeSpec) {
// 		if (ref->formalTypeSpec->size() != formalTypeSpec.size())
// 			return false;
// 		for (uint i = 0; i < formalTypeSpec.size(); ++i)
// 			if (!equal(ref->formalTypeSpec->at(i), formalTypeSpec.at(i)))
// 				return false;
// 	}
// 	
// 	if (ref->templateTypeSpec) {
// 		if (ref->templateTypeSpec->size() != templateTypeSpec.size())
// 			return false;
// 		for (uint i = 0; i < templateTypeSpec.size(); ++i)
// 			if (!equal(ref->templateTypeSpec->at(i), templateTypeSpec.at(i)))
// 				return false;
// 	}
// 	
// 	return true;
// }

bool TypeSpec::Before::operator()(const TypeSpec& a, const TypeSpec& b) {
	for (uint i = 0; i < max(a.templateTypeSpec.size(), b.templateTypeSpec.size()); ++i) {
		if (i >= a.templateTypeSpec.size())
			return true;
		if (i >= b.templateTypeSpec.size())
			return false;
		if (a.templateTypeSpec[i]->symbol < b.templateTypeSpec[i]->symbol)
			return true;
		if (b.templateTypeSpec[i]->symbol < a.templateTypeSpec[i]->symbol)
			return false;
	}
	
	for (uint i = 0; i < max(a.formalTypeSpec.size(), b.formalTypeSpec.size()); ++i) {
		if (i >= a.formalTypeSpec.size())
			return true;
		if (i >= b.formalTypeSpec.size())
			return false;
		if (before(a.formalTypeSpec[i], b.formalTypeSpec[i]))
			return true;
		if (before(b.formalTypeSpec[i], a.formalTypeSpec[i]))
			return false;
	}
	
	return false;
}
